﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Security;
using System.Text;
using System.Threading.Tasks;
using TPDF.Enums;

namespace TPDF
{
    internal class PdfiumWrapper
    {

        const string dllPath = "pdfium_x64.dll";

        [DllImport(dllPath, CallingConvention = CallingConvention.Cdecl)]
        [SuppressUnmanagedCodeSecurity]
        internal static extern void FPDF_InitLibrary();

        [DllImport(dllPath, CallingConvention = CallingConvention.Cdecl)]
        [SuppressUnmanagedCodeSecurity]
        internal static extern void FPDF_InitLibraryWithConfig(IntPtr config);

        [DllImport(dllPath, CallingConvention = CallingConvention.Cdecl)]
        [SuppressUnmanagedCodeSecurity]
        internal static extern void FPDF_DestroyLibrary();

        [DllImport(dllPath, CallingConvention = CallingConvention.Cdecl)]
        [SuppressUnmanagedCodeSecurity]
        internal static extern void FPDF_SetSandBoxPolicy(uint policy, bool enable);

        [DllImport(dllPath, CallingConvention = CallingConvention.Cdecl)]
        [SuppressUnmanagedCodeSecurity]
        internal static extern bool FPDF_SetPrintMode(int mode);

        [DllImport(dllPath, CallingConvention = CallingConvention.Cdecl)]
        [SuppressUnmanagedCodeSecurity]
        internal static extern IntPtr FPDF_LoadDocument(string file_path, string password);

        [DllImport(dllPath, CallingConvention = CallingConvention.Cdecl)]
        [SuppressUnmanagedCodeSecurity]
        internal static extern IntPtr FPDF_LoadMemDocument(IntPtr data_buf, int size, string password);

        [DllImport(dllPath, CallingConvention = CallingConvention.Cdecl)]
        [SuppressUnmanagedCodeSecurity]
        internal static extern IntPtr FPDF_LoadMemDocument64(IntPtr data_buf, ulong size, string password);

        [DllImport(dllPath, CallingConvention = CallingConvention.Cdecl)]
        [SuppressUnmanagedCodeSecurity]
        internal static extern IntPtr FPDF_LoadCustomDocument(IntPtr pFileAccess, string password);

        [DllImport(dllPath, CallingConvention = CallingConvention.Cdecl)]
        [SuppressUnmanagedCodeSecurity]
        internal static extern bool FPDF_GetFileVersion(IntPtr doc, int fileVersion);

        [DllImport(dllPath, CallingConvention = CallingConvention.Cdecl)]
        [SuppressUnmanagedCodeSecurity]
        internal static extern uint FPDF_GetLastError();

        [DllImport(dllPath, CallingConvention = CallingConvention.Cdecl)]
        [SuppressUnmanagedCodeSecurity]
        internal static extern bool FPDF_DocumentHasValidCrossReferenceTable(IntPtr document);

        [DllImport(dllPath, CallingConvention = CallingConvention.Cdecl)]
        [SuppressUnmanagedCodeSecurity]
        internal static extern uint FPDF_GetTrailerEnds(IntPtr document, IntPtr buffer, uint length);

        [DllImport(dllPath, CallingConvention = CallingConvention.Cdecl)]
        [SuppressUnmanagedCodeSecurity]
        internal static extern uint FPDF_GetDocPermissions(IntPtr document);

        [DllImport(dllPath, CallingConvention = CallingConvention.Cdecl)]
        [SuppressUnmanagedCodeSecurity]
        internal static extern int FPDF_GetSecurityHandlerRevision(IntPtr document);

        [DllImport(dllPath, CallingConvention = CallingConvention.Cdecl)]
        [SuppressUnmanagedCodeSecurity]
        internal static extern int FPDF_GetPageCount(IntPtr document);

        [DllImport(dllPath, CallingConvention = CallingConvention.Cdecl)]
        [SuppressUnmanagedCodeSecurity]
        internal static extern IntPtr FPDF_LoadPage(IntPtr document, int page_index);

        [DllImport(dllPath, CallingConvention = CallingConvention.Cdecl)]
        [SuppressUnmanagedCodeSecurity]
        internal static extern float FPDF_GetPageWidthF(IntPtr page);

        [DllImport(dllPath, CallingConvention = CallingConvention.Cdecl)]
        [SuppressUnmanagedCodeSecurity]
        internal static extern double FPDF_GetPageWidth(IntPtr page);

        [DllImport(dllPath, CallingConvention = CallingConvention.Cdecl)]
        [SuppressUnmanagedCodeSecurity]
        internal static extern float FPDF_GetPageHeightF(IntPtr page);

        [DllImport(dllPath, CallingConvention = CallingConvention.Cdecl)]
        [SuppressUnmanagedCodeSecurity]
        internal static extern double FPDF_GetPageHeight(IntPtr page);

        [DllImport(dllPath, CallingConvention = CallingConvention.Cdecl)]
        [SuppressUnmanagedCodeSecurity]
        internal static extern bool FPDF_GetPageBoundingBox(IntPtr page, IntPtr rect);

        [DllImport(dllPath, CallingConvention = CallingConvention.Cdecl)]
        [SuppressUnmanagedCodeSecurity]
        internal static extern bool FPDF_GetPageSizeByIndexF(IntPtr document, int page_index, IntPtr size);

        [DllImport(dllPath, CallingConvention = CallingConvention.Cdecl)]
        [SuppressUnmanagedCodeSecurity]
        internal static extern int FPDF_GetPageSizeByIndex(IntPtr document, int page_index, double width, double height);

        [DllImport(dllPath, CallingConvention = CallingConvention.Cdecl)]
        [SuppressUnmanagedCodeSecurity]
        internal static extern void FPDF_RenderPageBitmap(IntPtr bitmap, IntPtr page, int start_x, int start_y, int size_x, int size_y, int rotate, int flags);

        [DllImport(dllPath, CallingConvention = CallingConvention.Cdecl)]
        [SuppressUnmanagedCodeSecurity]
        internal static extern void FPDF_RenderPageBitmapWithMatrix(IntPtr bitmap, IntPtr page, IntPtr matrix, IntPtr clipping, int flags);

        [DllImport(dllPath, CallingConvention = CallingConvention.Cdecl)]
        [SuppressUnmanagedCodeSecurity]
        internal static extern void FPDF_ClosePage(IntPtr page);

        [DllImport(dllPath, CallingConvention = CallingConvention.Cdecl)]
        [SuppressUnmanagedCodeSecurity]
        internal static extern void FPDF_CloseDocument(IntPtr document);

        [DllImport(dllPath, CallingConvention = CallingConvention.Cdecl)]
        [SuppressUnmanagedCodeSecurity]
        internal static extern bool FPDF_DeviceToPage(IntPtr page, int start_x, int start_y, int size_x, int size_y, int rotate, int device_x, int device_y, double page_x, double page_y);

        [DllImport(dllPath, CallingConvention = CallingConvention.Cdecl)]
        [SuppressUnmanagedCodeSecurity]
        internal static extern bool FPDF_PageToDevice(IntPtr page, int start_x, int start_y, int size_x, int size_y, int rotate, double page_x, double page_y, int device_x, int device_y);

        [DllImport(dllPath, CallingConvention = CallingConvention.Cdecl, EntryPoint = "FPDFBitmap_Create")]
        [SuppressUnmanagedCodeSecurity]
        internal static extern IntPtr FPDFBitmapCreate(int width, int height, int alpha);

        [DllImport(dllPath, CallingConvention = CallingConvention.Cdecl, EntryPoint = "FPDFBitmap_CreateEx")]
        [SuppressUnmanagedCodeSecurity]
        internal static extern IntPtr FPDFBitmapCreateEx(int width, int height, int format, IntPtr first_scan, int stride);

        [DllImport(dllPath, CallingConvention = CallingConvention.Cdecl, EntryPoint = "FPDFBitmap_GetFormat")]
        [SuppressUnmanagedCodeSecurity]
        internal static extern int FPDFBitmapGetFormat(IntPtr bitmap);

        [DllImport(dllPath, CallingConvention = CallingConvention.Cdecl, EntryPoint = "FPDFBitmap_FillRect")]
        [SuppressUnmanagedCodeSecurity]
        internal static extern void FPDFBitmapFillRect(IntPtr bitmap, int left, int top, int width, int height, uint color);

        [DllImport(dllPath, CallingConvention = CallingConvention.Cdecl, EntryPoint = "FPDFBitmap_GetBuffer")]
        [SuppressUnmanagedCodeSecurity]
        internal static extern IntPtr FPDFBitmapGetBuffer(IntPtr bitmap);

        [DllImport(dllPath, CallingConvention = CallingConvention.Cdecl, EntryPoint = "FPDFBitmap_GetWidth")]
        [SuppressUnmanagedCodeSecurity]
        internal static extern int FPDFBitmapGetWidth(IntPtr bitmap);

        [DllImport(dllPath, CallingConvention = CallingConvention.Cdecl, EntryPoint = "FPDFBitmap_GetHeight")]
        [SuppressUnmanagedCodeSecurity]
        internal static extern int FPDFBitmapGetHeight(IntPtr bitmap);

        [DllImport(dllPath, CallingConvention = CallingConvention.Cdecl, EntryPoint = "FPDFBitmap_GetStride")]
        [SuppressUnmanagedCodeSecurity]
        internal static extern int FPDFBitmapGetStride(IntPtr bitmap);

        [DllImport(dllPath, CallingConvention = CallingConvention.Cdecl, EntryPoint = "FPDFBitmap_Destroy")]
        [SuppressUnmanagedCodeSecurity]
        internal static extern void FPDFBitmapDestroy(IntPtr bitmap);

        [DllImport(dllPath, CallingConvention = CallingConvention.Cdecl)]
        [SuppressUnmanagedCodeSecurity]
        internal static extern bool FPDF_VIEWERREF_GetPrintScaling(IntPtr document);

        [DllImport(dllPath, CallingConvention = CallingConvention.Cdecl)]
        [SuppressUnmanagedCodeSecurity]
        internal static extern int FPDF_VIEWERREF_GetNumCopies(IntPtr document);

        [DllImport(dllPath, CallingConvention = CallingConvention.Cdecl)]
        [SuppressUnmanagedCodeSecurity]
        internal static extern IntPtr FPDF_VIEWERREF_GetPrintPageRange(IntPtr document);

        [DllImport(dllPath, CallingConvention = CallingConvention.Cdecl)]
        [SuppressUnmanagedCodeSecurity]
        internal static extern ulong FPDF_VIEWERREF_GetPrintPageRangeCount(IntPtr pagerange);

        [DllImport(dllPath, CallingConvention = CallingConvention.Cdecl)]
        [SuppressUnmanagedCodeSecurity]
        internal static extern int FPDF_VIEWERREF_GetPrintPageRangeElement(IntPtr pagerange, ulong index);

        [DllImport(dllPath, CallingConvention = CallingConvention.Cdecl)]
        [SuppressUnmanagedCodeSecurity]
        internal static extern FPDF_DUPLEXTYPE FPDF_VIEWERREF_GetDuplex(IntPtr document);

        [DllImport(dllPath, CallingConvention = CallingConvention.Cdecl)]
        [SuppressUnmanagedCodeSecurity]
        internal static extern uint FPDF_VIEWERREF_GetName(IntPtr document, string key, IntPtr intPtr, uint length);

        [DllImport(dllPath, CallingConvention = CallingConvention.Cdecl)]
        [SuppressUnmanagedCodeSecurity]
        internal static extern uint FPDF_CountNamedDests(IntPtr document);

        [DllImport(dllPath, CallingConvention = CallingConvention.Cdecl)]
        [SuppressUnmanagedCodeSecurity]
        internal static extern IntPtr FPDF_GetNamedDestByName(IntPtr document, string name);

        [DllImport(dllPath, CallingConvention = CallingConvention.Cdecl)]
        [SuppressUnmanagedCodeSecurity]
        internal static extern IntPtr FPDF_GetNamedDest(IntPtr document, int index, IntPtr buffer, int buflen);

        [DllImport(dllPath, CallingConvention = CallingConvention.Cdecl)]
        [SuppressUnmanagedCodeSecurity]
        internal static extern int FPDF_GetXFAPacketCount(IntPtr document);

        [DllImport(dllPath, CallingConvention = CallingConvention.Cdecl)]
        [SuppressUnmanagedCodeSecurity]
        internal static extern uint FPDF_GetXFAPacketName(IntPtr document, int index, IntPtr buffer, uint buflen);

        [DllImport(dllPath, CallingConvention = CallingConvention.Cdecl)]
        [SuppressUnmanagedCodeSecurity]
        internal static extern bool FPDF_GetXFAPacketContent(IntPtr document, int index, IntPtr buffer, uint buflen, uint out_buflen);
    }
    internal class TpdfHelper
    {
        public static bool IsLoaded { get; private set; } = false;
        /// <summary>
        /// 初始化
        /// </summary>
        public static void Init()
        {
            try
            {
                PdfiumWrapper.FPDF_InitLibrary();
            }
            catch (Exception ex)
            {
                Console.WriteLine("init tpdf error" + ex.Message + ex.StackTrace);
                IsLoaded = false;
                return;
            }
            IsLoaded = true;
        }

        internal static void ClosePage(IntPtr pageIntPtr)
        {
            PdfiumWrapper.FPDF_ClosePage(pageIntPtr);
        }

        internal static void DestoryBitmap(IntPtr dataIntPtr)
        {
           PdfiumWrapper.FPDFBitmapDestroy(dataIntPtr);
        }

        internal static IntPtr FPDFBitmapCreateEx(int width, int height, int bitmapFormat, IntPtr backBuffer, int backBufferStride)
        {
            return PdfiumWrapper.FPDFBitmapCreateEx(width, height, bitmapFormat, backBuffer, backBufferStride);
        }

        internal static void FPDF_RenderPageBitmap(IntPtr image, IntPtr pageIntPtr, int v1, int v2, int width, int height, int orientations, int renderingFlags)
        {
            PdfiumWrapper.FPDF_RenderPageBitmap(image, pageIntPtr, v1, v2, width, height, orientations, renderingFlags);
        }

        internal static IntPtr GetPage(IntPtr intPtr, int pageIndex)
        {
            return PdfiumWrapper.FPDF_LoadPage(intPtr, pageIndex);
        }

        internal static int GetPageCount(IntPtr pdfIntPtr)
        {
            return PdfiumWrapper.FPDF_GetPageCount(pdfIntPtr);
        }

        internal static double GetPageHeight(IntPtr intPtr)
        {
            return PdfiumWrapper.FPDF_GetPageHeight(intPtr);
        }

        internal static double GetPageWidth(IntPtr intPtr)
        {
            return PdfiumWrapper.FPDF_GetPageWidth(intPtr);
        }

        internal static IntPtr LoadDocument(string filePath, string password)
        {
            return PdfiumWrapper.FPDF_LoadDocument(filePath, password);
        }
    }
}
